﻿using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using ChessRun.Engine.Moves;
using ChessRun.Engine.Utils;
using ChessRun.Rasterizer;

namespace ChessRun.Engine.Diagnostics.Docs {
    class Program {

        static void Main(string[] args1) {
            StringBuilder sb = new StringBuilder();

            var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("ChessRun.Engine.Diagnostics.Docs.Resources.perftsuite.epd");
            if (resource == null) throw new InvalidOperationException("Test resource is not found");
            var boardIndex = 0;
            using (var reader = new StreamReader(resource)) {
                int lineIndex = 0;
                while (!reader.EndOfStream) {
                    var line = reader.ReadLine();
                    lineIndex++;
                    line = line.Trim();
                    if (line.StartsWith("#") || line == string.Empty) continue;
                    var args = line.Split(';');
                    string fen = args[0];
                    var board = new ChessBoard();
                    FEN.Setup(board, fen);

                    var hash = HashBoard(board);
                    sb.AppendFormat("! Test Suit {0}\r\n", boardIndex);
                    sb.AppendLine();
                    sb.AppendFormat("FEN: {0}\r\n", fen);
                    sb.AppendFormat("Turn: {0}\r\n", board.Turn);
                    sb.AppendFormat("[image:{0}.png]", hash);
                    sb.AppendLine();

                    board.GenerateValidMoves(new DocDivideIterator(sb, board, 5));

                    sb.AppendLine();
                    sb.AppendLine();

                    var rasterizer = new ChessBoardRasterizer();
                    var img = rasterizer.Rasterize(board, 424);
                    img.Save(hash + ".png");
                    boardIndex++;
                }
            }
            Console.Write(sb.ToString());
        }

        public static string HashBoard(ChessBoard board) {
            var fen = FEN.GetFEN(board);
            var bytes = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(fen));
            var res = "";
            var hex = "0123456789abcdef";
            foreach (var bt in bytes) {
                res += hex[bt >> 4] + hex[bt & 15];
            }
            return res;
        }

        public class DocDivideIterator : MovesIterator {
            private readonly StringBuilder _sb;
            private int _depth;
            private readonly int _originalDepth;
            private ulong _currentMoveNodes;
            public ulong TotalMoveNodes;

            public DocDivideIterator(StringBuilder sb, ChessBoard board, int depth)
                : base(board) {
                _sb = sb;
                _depth = depth;
                _originalDepth = _depth;
            }


            public sealed override void Handle(SpeculativeMove move) {
                if (_depth == _originalDepth) {
                    var sn = move.From.ToString().ToLower() + move.To.ToString().ToLower();
                    _sb.Append(sn + " ");
                    _currentMoveNodes = 0;
                }
                if (_depth > 1) {
                    _depth--;
                    _board.GenerateValidMoves(this);
                    _depth++;
                } else {
                    _currentMoveNodes++;
                    TotalMoveNodes++;
                }
                if (_depth == _originalDepth) {
                    _sb.Append(_currentMoveNodes + "\r\n");
                }

            }

        }
    }
}
